package com.smart.common.hander;

import com.smart.common.exception.BaseException;
import com.smart.common.exception.ControllerException;
import com.smart.common.exception.DaoException;
import com.smart.common.exception.ServiceException;
import com.smart.common.vo.ResponseEnumCode;
import com.smart.common.vo.ResponseResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import java.util.List;
import java.util.stream.Collectors;


@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    /**
     * 实体参数类错误的异常处理
     *
     * @param exception
     * @return
     * @throws Exception
     */
    @ExceptionHandler({MethodArgumentNotValidException.class, BindException.class})
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResponseResult<String> methodArgumentNotValidHandler(
            MethodArgumentNotValidException exception) throws Exception {
        //按需重新封装需要返回的错误信息
        BindingResult bindingResult = exception.getBindingResult();
        List<String> errors = exception.getBindingResult().getAllErrors()
                .stream()
                .map(ObjectError::getDefaultMessage)
                .collect(Collectors.toList());
        return ResponseResult.error(errors.get(0));
    }


    /**
     * ConstraintViolationException
     * 单个参数违反约束校验异常
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public ResponseResult<String> handleConstraintViolationException(ConstraintViolationException e) {
        log.error(e.getMessage(), e);
        return ResponseResult.error();
    }

    @ExceptionHandler(BaseException.class)
    public ResponseResult<Object> handler(BaseException ex) {
        log.error(ex.getMsg());
        return ResponseResult.error(ex.getResponseEnumCode());
    }

    /**
     * 未知异常处理
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(Exception.class)
    public ResponseResult<Object> handler(Exception ex) {
        log.error(ex.getMessage());
        return ResponseResult.error();
    }

    @ExceptionHandler(ServiceException.class)
    public ResponseResult<Object> handler(ServiceException ex) {
        log.error(ex.getMsg());
        return ResponseResult.error(ex.getResponseEnumCode());
    }


    @ExceptionHandler(DaoException.class)
    public ResponseResult<Object> handler(DaoException ex) {
        log.error(ex.getMsg());
        return ResponseResult.error(ex.getResponseEnumCode());
    }

    @ExceptionHandler(ControllerException.class)
    public ResponseResult<Object> handler(ControllerException ex) {
        log.error(ex.getMsg());
        return ResponseResult.error(ex.getResponseEnumCode());
    }


    /**
     * Bean校验通用异常
     * ValidationException
     */
    @ExceptionHandler(ValidationException.class)
    public ResponseResult<String> handleValidationException(ValidationException e) {
        log.error(e.getMessage(), e);
        return ResponseResult.error("参数错误");
    }

    /**
     * 404 错误
     */
    @ExceptionHandler(NoHandlerFoundException.class)
    public ResponseResult<Object> handlerNoFoundException(Exception e) {
        log.error(e.getMessage(), e);
        return ResponseResult.error(ResponseEnumCode.ERROR);
    }

}
